#pragma once

#if !defined(_MAPKIT_H_)
#define _MAPKIT_H_

#include "MKdef.h"
#include "MKTools.h"
#include <vector>

class MK_API MapKit
{
public:
    typedef std::pair<double, double> coord_t;
    typedef std::vector<coord_t> vtvec_t;
    typedef struct _cell_t
    {
        coord_t A;
        coord_t B;
        coord_t C;

        void Sort();
        bool operator==(const _cell_t& c);
    } cell_t;
    typedef std::vector<cell_t> cvec_t;
    typedef std::vector<MKVertex*> mkpvtvec_t;
    typedef std::vector<MKTriangle*> mkptrivec_t;
public:
    MapKit();
    virtual ~MapKit();

    void SetSize(const double& w, const double& h);

    void Randomize(const unsigned int& seed);
    static double RandDouble();
    void GetPoisson(const double& r, const uint32_t& k = 30);
    void FractalAltitude(double ratio);
    void PerlinNoiseAltitude();
    double AltitudeLinearSampler2D(const double& x, const double& y);

    void Triangulate();

    const mkpvtvec_t* GetVertices() const;
    const mkptrivec_t* GetTriangles() const;
    const int GetFractalSize();
    const std::vector<std::vector<double>>* GetAltitude() const;
protected:
    double width = 0, height = 0;
    vtvec_t* coords = nullptr;
    mkpvtvec_t* vertices = nullptr;
    mkptrivec_t* triangles = nullptr;
    int fractalSize = 0;
    std::vector<std::vector<double>>* altitude = nullptr;

    static void ConvexHull(vtvec_t*& res, const vtvec_t* _vts);
    static bool FindCommon(coord_t& va, coord_t& vb, coord_t& opposite1, coord_t& opposite2, const cell_t& t1, const cell_t& t2);
    static bool IsVertexInCircumcircle(const coord_t& A, const coord_t& B, const coord_t& C, const coord_t& P);
    static bool IsVertexInCell(const cell_t& c, const coord_t& vt);
    static coord_t FindCircumCircle(double& radius, const coord_t& A, const coord_t& B, const coord_t& C);
};

#endif